
/*
 * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
 *
 * (b)  If this Sample Code is distributed as part of the Display PostScript
 *	System Software Development Kit from Adobe Systems Incorporated,
 *	then this copy is designated as Development Software and its use is
 *	subject to the terms of the License Agreement attached to such Kit.
 *
 * (c)  If this Sample Code is distributed independently, then the following
 *	terms apply:
 *
 * (d)  This file may be freely copied and redistributed as long as:
 *	1) Parts (a), (d), (e) and (f) continue to be included in the file,
 *	2) If the file has been modified in any way, a notice of such
 *      modification is conspicuously indicated.
 *
 * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
 *	Adobe Systems Incorporated.
 * 
 * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
 *	CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
 *	AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
 *	ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
 *	OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
 *	WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
 *	WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
 *	DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
 *	FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
 *	OF THIRD PARTY RIGHTS.
 */

/*
 *	GraphicList.m
 *
 *	This class is used to simplify the messaging of the graphics.
 *	Eliminates the need to walk the list in DrawingView.
 *
 *	Version:	2.0
 *	Author:	Ken Fromm
 */

#import "GraphicList.h"
#import "GraphicImport.h"
#import "DrawingView.h"

#import <appkit/nextstd.h>
#import <dpsclient/wraps.h>

@implementation GraphicList

- copy
{
	id		copyId;

	int		i;

	copyId = [GraphicList  newCount:numElements];
	for (i = 0; i < numElements; i++)
		[copyId  insertObject:[self  objectAt:i]  at:i];

	return copyId;
}

- copyTemp
{
	id		copyId;

	int		i;

	copyId = [GraphicList  newCount:numElements];
	for (i = 0; i < numElements; i++)
		[copyId  insertObject:[[self  objectAt:i]  copyTemp]  at:i];

	return copyId;
}

- freeTemp
{
	int		i;

	for (i = 0; i < numElements; i++)
		[[self  objectAt:i]  freeTemp];

	return self;
}

- replaceObjectsIn:aList  with:bList
{
	int		i, j;

	j = [aList  count];
	for (i = 0; i  < j; i++)
	{
		if (![self  replaceObject:[aList  objectAt:i]  with:[bList  objectAt:i]])
			[self  insertObject:[bList  objectAt:i]  at:0];
	}

	return self;
}

- removeObjectsIn:bList
{
	int		i, j;

	j = [bList  count];
	for (i = 0; i  < j; i++)
		[self  removeObject:[bList  objectAt:i]];

	return self;
}

- insertObjectsIn:bList
{
	int		i, j;

	j = [bList  count];
	for (i = j-1; i  >= 0; i--)
		[self  insertObject:[bList  objectAt:i]  at:0];

	return self;
}

/* Set all the objects in the list to either selected or not. */
- setSelected:(BOOL) flag
{
	int		i;
	
	for (i = numElements - 1; i  >= 0; i--)
		[[self  objectAt:i]  setSelected:flag];
	
	return self;
}

/* Reflect the rotation in all the objects of the list. */
- rotateAboutPoint:(NXPoint *) aPoint  withAngle:(float) angle
{
	int		i;
	
	for (i = numElements - 1; i  >= 0; i--)
		[[self  objectAt:i]  rotateAboutPoint:aPoint  withAngle:angle];
	
	return self;
}

/* Reflect the change in all the objects of the list. */
- moveAll:(const NXPoint *) pt
{
	int		i;
	
	for (i = numElements - 1; i  >= 0; i--)
		[[self  objectAt:i]  moveAll:pt];
	
	return self;
}

/*
*	Returns the bounds.  The flag variable determines whether the
*	knobs should be factored in. They may need to be for drawing but
*	might not if needed for constraining reasons.
*/
- getBounds:(NXRect *)aRect
{
	int		i;
	
	NXRect 	bRect;

	for (i = numElements - 1; i  >= 0; i--)
	{
		[[self  objectAt:i] getBounds:&bRect];
		if (i == numElements - 1)
			*aRect = bRect;
		else
			NXUnionRect(&bRect, aRect);
	}

	return self;
}

/*
*	Return the rectangle that should be used for scrolling purposes.
*	When the rectangle passes out of the visible rectangle then
*	the screen should scroll.
*/
- getScrollRect:(NXRect *)aRect  forPtNum:(int) pt_num
{
	return [self  getBounds:aRect];
}

- constrainAngle:(float *) angle  withFlags:(int)flags
{
	[[self  objectAt:0]  constrainAngle:angle  withFlags:flags];

	return self;
}

/*
*	Check for a control point hit on all the objects in the list. If yes then return
*	the hit object.
*/
- hitControl:(const NXRect *) hitRect  :(int *) pt_num  forSize:(float) size
{
	id		objectId;

	int		i;
	
	for (i = 0; i < numElements; i++)
		if (objectId = [[self  objectAt:i]  hitControl:hitRect :pt_num  forSize:(float) size])
			return objectId;

	return nil;
}

/*
*	Place the point locations and the chararacters for the control
*	points of the objects in the list into the user path description.
*/
- putControlPoints:(UPath *)buffer  forRect:(NXRect *)r  :(NXPoint *) lastPoint
{
	int	i;
	
	for (i = numElements - 1; i  >= 0; i--)
		[[self  objectAt:i]  putControlPoints:buffer  forRect:r  :lastPoint];

	return self;
}

/*
 *	Draws the graphic.
 */
- drawObject:(NXRect *) r  withFlags:(int) flags  inView:view
{
	id		graphic;

	int		i;

	for (i = numElements - 1; i  >= 0; i--)
	{
		graphic = [self  objectAt:i];
		[graphic  drawObject:r  withFlags:flags  inView:view];

		if (NXDrawingStatus == NX_DRAWING &&
			flags & REFRESHFLAG &&
				[graphic  isKindOf:[GraphicImport class]])
		{
			/*
			*  Relies on the assumption that the buffer is the currently
			*  focused view. This refreshes the screen with each EPSF file.
			*  If not then it could take a while to have some visual results
			*  when imaging several files in a row.
			*/
			[[view  buffer]  unlockFocus];
 			PScomposite(NX_X(r), NX_Y(r), NX_WIDTH(r), NX_HEIGHT(r),
                		[[view  buffer]  gState], r->origin.x, r->origin.y, NX_COPY);
			[[view  buffer]  lockFocus];
		}
	}

	return self;
}

- addResources:(Resource *) resourceDoc  for:(NXRect *) r
{
	id		graphic;

	int		i;

	for (i = numElements - 1; i  >= 0; i--)
	{
		graphic = [self  objectAt:i];
		if ([graphic  isKindOf:[GraphicImport class]])
			[graphic  addResources:resourceDoc  for:r];
	}

	return self;
}

@end

